package com.dragon.logical.service.contract.impl;

import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.dragon.common.model.ResultCode;
import com.dragon.common.model.exception.CustomException;
import com.dragon.logical.service.contract.IEquipmentService;
import com.dragon.logical.service.contract.IProduceSchedulingService;
import com.dragon.logical.service.contract.ProduceService;
import com.dragon.repository.entity.*;
import com.dragon.repository.mapper.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * <p>
 * 生产的排产表 服务实现类
 * </p>
 *
 * @author sy
 * @since 2023-11-29
 */
@Service
public class ProduceSchedulingServiceImpl extends ServiceImpl<ProduceSchedulingMapper, ProduceScheduling> implements IProduceSchedulingService {

    @Autowired
    ProduceSchedulingMapper produceSchedulingMapper;
    @Autowired
    EquipmentMapper equipmentMapper;
    @Autowired
    IEquipmentService equipmentService;
    @Autowired
    ProduceMapper produceMapper;
    @Autowired
    ProduceProductsMapper produceProductsMapper;
    @Autowired
    SchedulingSonMapper schedulingSonMapper;
    @Autowired
    ProduceService produceService;
    @Autowired
    RejectedMapper rejectedMapper;
    @Autowired
    RejectedProductMapper rejectedProductMapper;
    @Autowired
    SchedulingSonSonMapper sonSonMapper;



    @Override
    public Page<ProduceScheduling> produceSchedulingList(Integer page, Integer limit, Integer type){
        Page<ProduceScheduling> schedulePage = new Page<>(page, limit);
        Page<ProduceScheduling> produceSchedulePage = produceSchedulingMapper.selectDetailList(schedulePage,type);
        produceSchedulePage.getRecords().forEach(produceScheduling -> {
            List<SchedulingSon> sonList = schedulingSonMapper.getListBySchedulingId(produceScheduling.getId(),null, null);
            produceScheduling.setSchedulingSonList(sonList);
        });
        return produceSchedulePage;
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public void produceSchedulingAdd(ProduceScheduling produceScheduling) {
        produceScheduling.setStartTime(DateUtil.date());
        produceSchedulingMapper.insert(produceScheduling);
        //修改生产单的排产状态
        List<Integer> idList = Stream.of(produceScheduling.getProduceId().split(","))
                .map(Integer::valueOf).collect(Collectors.toList());
        idList.forEach(produceId -> {
            Produce produce = produceMapper.selectById(produceId);
            produce.setType(1);
            produce.setSchedulingStatus(1);
            produceMapper.updateById(produce);
        });
        List<Equipment> equipmentList = equipmentMapper.selectList(new LambdaQueryWrapper<Equipment>()
                .in(Equipment::getId,produceScheduling.getSchedulingSonList().stream().map(SchedulingSon::getEquipmentId).distinct().collect(Collectors.toList()))
                .eq(Equipment::getType,1)
        );
        if(equipmentList.size() > 0){
            String error = equipmentList.stream().map(Equipment::getEquipmentCode).collect(Collectors.joining(",")).concat("设备已经开始生产，请重新分配设备");
            throw new CustomException(ResultCode.ERROR.code(),error);
        }
        produceScheduling.getSchedulingSonList().forEach(schedulingSon -> {
            //添加子表
            schedulingSon.setCreateTime(DateUtil.date());
            schedulingSon.setSchedulingId(produceScheduling.getId());
            schedulingSonMapper.insert(schedulingSon);
            //修改生产产品子表信息
            QueryWrapper<ProduceProducts> wrapper = new QueryWrapper<>();
            wrapper.lambda().eq(ProduceProducts::getProduceId,schedulingSon.getProduceId())
                    .eq(ProduceProducts::getQuotesProductId,schedulingSon.getProductId());
            ProduceProducts produceProducts = produceProductsMapper.selectOne(wrapper);

            // 该生产单已经生产完毕了
            if(produceProducts.getNum().equals(produceProducts.getScheduledNum())){
                //执行下一次循环
                return;
            }

            produceProducts.setScheduledNum(produceProducts.getScheduledNum() + schedulingSon.getSchedulingNum());
            produceProducts.setProduceStatus(1);

            if (produceProducts.getNum() <= produceProducts.getScheduledNum()){
                produceProducts.setSchedulingStatus(2);
            }else {
                produceProducts.setSchedulingStatus(1);
            }
            produceProducts.setUpdateTime(DateUtil.date());
            produceProductsMapper.updateById(produceProducts);

            //判断当前排产子表 是否拆解键
            if (schedulingSon.getIsDismantle() == 1){
                //sonList.addAll(schedulingSon.getSonSonList());
                schedulingSon.getSonSonList().forEach(schedulingSonSon -> {
                    schedulingSonSon.setSchedulingId(produceScheduling.getId());
                    schedulingSonSon.setProduceId(schedulingSon.getProduceId());
                    schedulingSonSon.setSchedulingSonId(schedulingSon.getId());
                    schedulingSonSon.setProductId(schedulingSon.getProductId());
                    schedulingSonSon.setCreateTime(DateUtil.date());
                    sonSonMapper.insert(schedulingSonSon);
                    // 修改设备的生产截至时间
                    Equipment equipment = equipmentMapper.selectById(schedulingSonSon.getEquipmentId());
                    Integer second = (int) (schedulingSonSon.getFinishHour()*3600);
                    //修改设备状态 和 时间
                    if(equipment.getType()==0){
                        equipment.setType(1);
                    }
                    Date finishTime = null;
                    if(equipment.getEstimateFinishTime().equals(DateUtil.parse("2000-01-01 00:00:00"))){
                        finishTime = DateUtil.date();
                    } else {
                        finishTime = equipment.getEstimateFinishTime();
                    }
                    equipment.setEstimateFinishTime(DateUtil.offsetSecond(finishTime, second));
                    equipmentMapper.updateById(equipment);
                });
            } else {

                // 修改设备的生产截至时间
                Equipment equipment = equipmentMapper.selectById(schedulingSon.getEquipmentId());
                Integer second = (int) (schedulingSon.getFinishHour()*3600);
                //修改设备状态 和 时间
                if(equipment.getType()==0){
                    equipment.setType(1);
                }
                Date finishTime = null;
                if(equipment.getEstimateFinishTime() == null||equipment.getEstimateFinishTime().equals(DateUtil.parse("2000-01-01 00:00:00"))){
                    finishTime = DateUtil.date();
                } else {
                    finishTime = equipment.getEstimateFinishTime();
                }
                equipment.setEstimateFinishTime(DateUtil.offsetSecond(finishTime, second));
                equipmentMapper.updateById(equipment);
                //判断生产单是否 从退货来
                Produce produce = produceMapper.selectById(schedulingSon.getProduceId());
                if (produce.getSource() == 1){
                    //修改 退货产品中的 已处理数量
                    Rejected rejected = rejectedMapper.selectById(produce.getRejectedId());
                    QueryWrapper<RejectedProduct> wrapper1 = new QueryWrapper<>();
                    wrapper1.lambda().eq(RejectedProduct::getRejectedId,rejected.getId())
                            .eq(RejectedProduct::getProductId,schedulingSon.getProductId());
                    RejectedProduct rejectedProduct = rejectedProductMapper.selectOne(wrapper1);
                    int processNum = rejectedProduct.getProcessingNum() + schedulingSon.getSchedulingNum();
                    //添加正在处理的数量
                    rejectedProduct.setProcessingNum( processNum );
                    rejectedProductMapper.updateById(rejectedProduct);
                }
            }
        });

        //修改所有设备的状态
//        Equipment equipment = new Equipment();
//
//        equipment.setType(1);
//
//        equipment.setUpdateTime(DateUtil.date());
//
//        equipmentMapper.update(equipment,new LambdaQueryWrapper<Equipment>().in(Equipment::getId,equimentIds.stream().distinct().collect(Collectors.toList())));
//
//        if(equipment.getType() == 1){
//            throw new CustomException(ResultCode.ERROR.code(),equipment.getEquipmentName().concat("该设备已在生产中"));
//        }

        //获取当前排产子表下的 设备id（去重）
//        List<Integer> equipmentIds = produceScheduling.getSchedulingSonList()
//                .stream()
//                .distinct()
//                .map(SchedulingSon::getEquipmentId)
//                .collect(Collectors.toList());
//        equipmentIds.forEach(equipmentId -> {
//            List<SchedulingSon> sonList = schedulingSonMapper.selectList(new QueryWrapper<SchedulingSon>()
//                    .lambda()
//                    .eq(SchedulingSon::getEquipmentId, equipmentId)
//                    .eq(SchedulingSon::getType,1));
//            //获取 完成小时
//            Double hour = sonList.stream().map(e -> e.getFinishHour()).reduce(Double.valueOf(0), (a, b) -> a + b);
//            Integer second = (int) (hour * 3600);
//            //修改设备状态 和 时间
//            Equipment equipment = equipmentMapper.selectById(equipmentId);
//            equipment.setType(1);
//            equipment.setEstimateFinishTime(DateUtil.offsetSecond(produceScheduling.getStartTime(), second));
//            equipmentMapper.updateById(equipment);
//        });

        //修改设备状态
//        Equipment equipment = equipmentMapper.selectById(produceScheduling.getEquipmentId());
//        equipment.setType(1);
//        equipmentMapper.updateById(equipment);
        List<Integer> ids = Stream.of(produceScheduling.getProduceId().split(",")).map(Integer::valueOf).collect(Collectors.toList());
        ids.forEach(produceId->{
            equipmentService.updateProduceType(produceId);
        });
    }


    @Override
    public List<Produce> getProduceList(String ids) {
        List<Produce> produceList = new ArrayList<>();
        List<Integer> produceIds = Stream.of(ids.split(",")).map(Integer::valueOf).collect(Collectors.toList());
        produceIds.forEach(produceId -> {
            Produce produce = produceService.selectProduceById(produceId);
            produceList.add(produce);
        });
        return produceList;
    }
}
